package com.shanzhe.eshop.common.nio;

import lombok.SneakyThrows;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;

/**
 * @Author yinwei
 * @create 2021/12/25
 * @Version 1.0
 */
public class NIOClient {

    private static CharsetEncoder encoder =  Charset.forName("UTF-8").newEncoder();
    private static CharsetDecoder decoder =  Charset.forName("UTF-8").newDecoder();;

    public static void main(String[] args) {
        for(int i = 0;i<10;i++){
            new Worker().start();
        }
    }


    static class Worker extends Thread{
        @SneakyThrows
        @Override
        public void run() {
            SocketChannel socketChannel = null;
            Selector selector = null;
            try {


                //SocketChannel底层就封装了socket 就是负责网络读写数据
                socketChannel = SocketChannel.open();
                socketChannel.configureBlocking(false);

                //底层发起tcp三次握手建立连接
                socketChannel.connect(new InetSocketAddress("localhost",9000));

                //注册用于selector监听socketchannel
                selector = Selector.open();
                socketChannel.register(selector, SelectionKey.OP_CONNECT);
                while (true){
                    //服务器会和客户端返回响应
                    selector.select();

                    Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
                    if(keys.hasNext()){
                         SelectionKey key = keys.next();
                         keys.remove();

                         //如果是可以进行连接的消息
                         if(key.isConnectable()){
                             if(socketChannel.isConnectionPending()){
                                    //如果三次握手连接成功
                                    socketChannel.finishConnect();
                                    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
                                    byteBuffer.put("你好".getBytes());
                                    Thread.sleep(1000);
                                    byteBuffer.flip();
                                    socketChannel.write(byteBuffer);
                             }
                             socketChannel.register(selector,SelectionKey.OP_READ);
                         }else if(key.isReadable()){
                             ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024);
                             socketChannel.read(buffer);
                             buffer.flip();
                             CharBuffer charBuffer = decoder.decode(buffer);
                             String response = charBuffer.toString();
                             System.out.println(Thread.currentThread().getName()+response);

                             socketChannel.register(selector,SelectionKey.OP_WRITE);
                         }else if(key.isWritable()){
                             socketChannel = (SocketChannel) key.channel();

                             ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
                             byteBuffer.put("发起请求".getBytes());
                             byteBuffer.flip();
                             socketChannel.write(byteBuffer);
                             socketChannel.register(selector,SelectionKey.OP_READ);
                         }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if(socketChannel!=null){
                    socketChannel.close();
                }
            }
        }
    }
}
